using System;
using System.Collections.Generic;
using System.Text;
using Barrage.Render;

namespace Barrage
{
    /// <summary>
    /// Represents a section of the game, such as a menu or a subgame
    /// </summary>
    public abstract class GameSection:IDisposable
    {
        /// <summary>
        /// Gets the section Id
        /// </summary>
        public abstract int Id { get;}
        /// <summary>
        /// Section scenes
        /// </summary>
        protected List<Scene> scenes;
        /// <summary>
        /// Render processes of this section
        /// </summary>
        protected List<RenderProcess> renderProcesses;

        /// <summary>
        /// Render processes of this section
        /// </summary>
        public List<RenderProcess> RenderProcesses { get { return renderProcesses; } }

        /// <summary>
        /// First render process of this section
        /// </summary>
        public RenderProcess DefaultRenderProcess { get { if (renderProcesses.Count > 0) return renderProcesses[0]; return null; } }
        /// <summary>
        /// First scene of this section
        /// </summary>
        public Scene DefaultScene { get { if (scenes.Count > 0) return scenes[0]; return null; } }

        /// <summary>
        /// The Game parent of this game section
        /// </summary>
        protected Game parent;
        /// <summary>
        /// The Game parent of this game section
        /// </summary>
        public Game Parent { get { return parent; } }

        /// <summary>
        /// Base constructor
        /// </summary>
        /// <param name="parent">Parent of this game section</param>
        public GameSection(Game parent)
        {
            scenes = new List<Scene>();
            renderProcesses = new List<RenderProcess>();
            this.parent = parent;
        }

        /// <summary>
        /// Inits the section (Scenes and Render Processes)
        /// </summary>
        public virtual void InitSection()
        {
            initScenes();
            initRenderProcesses();
        }

        /// <summary>
        /// Abstract method: Init the section scenes
        /// </summary>
        protected abstract void initScenes();

        /// <summary>
        /// Clears the render process list
        /// </summary>
        protected virtual void clearRenderProcesses()
        {
            renderProcesses.Clear();
        }

        /// <summary>
        /// Adds a render process to the list
        /// </summary>
        /// <param name="rp">The render process to be added</param>
        public void AddRenderProcess(RenderProcess rp)
        {
            renderProcesses.Add(rp);
        }

        /// <summary>
        /// Inits the render processes of the section
        /// </summary>
        protected virtual void initRenderProcesses()
        {
            RenderProcess rp = new RenderProcess();
            rp.addSource(DefaultScene);
            renderProcesses.Add(rp);
        }

        /// <summary>
        /// Add a scene to the scene list
        /// </summary>
        /// <param name="s">Scene to be added</param>
        public void AddScene(Scene s)
        {
            scenes.Add(s);
        }

        /// <summary>
        /// Updates every scene in the scene list
        /// </summary>
        public virtual void UpdateScenes()
        {
            foreach (Scene s in scenes)
            {
                Scene.CurrentInstance = s;
                s.Update();
            }
            Scene.CurrentInstance = null;
        }

        /// <summary>
        /// Section main loop. Must be overrided
        /// </summary>
        public abstract void MainLoop();

        /// <summary>
        /// Free resources
        /// </summary>
        public virtual void Dispose()
        {
            scenes.Clear();
            scenes = null;
            renderProcesses.Clear();
            renderProcesses = null;
            parent = null;
            NLog.LogManager.GetLogger(ToString()).Debug("Disposing"); 
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Destructor. Free resources
        /// </summary>
        ~GameSection()
        {
            Dispose();
        }
    }
}
